home *** CD-ROM | disk | FTP | other *** search
/ American Osteopathic Ass…tion Yearbook 2005 & 2006 / American Osteopathic Association Yearbook 2005 & 2006.iso / mac / app / bdb.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2004-07-22  |  23.5 KB  |  627 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.3)
  3.  
  4. '''Debugger basics'''
  5. import sys
  6. import os
  7. import types
  8. __all__ = [
  9.     'BdbQuit',
  10.     'Bdb',
  11.     'Breakpoint']
  12.  
  13. class BdbQuit(Exception):
  14.     '''Exception to give up completely'''
  15.     pass
  16.  
  17.  
  18. class Bdb:
  19.     '''Generic Python debugger base class.
  20.  
  21.     This class takes care of details of the trace facility;
  22.     a derived class should implement user interaction.
  23.     The standard debugger class (pdb.Pdb) is an example.
  24.     '''
  25.     
  26.     def __init__(self):
  27.         self.breaks = { }
  28.         self.fncache = { }
  29.  
  30.     
  31.     def canonic(self, filename):
  32.         if filename == '<' + filename[1:-1] + '>':
  33.             return filename
  34.         
  35.         canonic = self.fncache.get(filename)
  36.         if not canonic:
  37.             canonic = os.path.abspath(filename)
  38.             canonic = os.path.normcase(canonic)
  39.             self.fncache[filename] = canonic
  40.         
  41.         return canonic
  42.  
  43.     
  44.     def reset(self):
  45.         import linecache
  46.         linecache.checkcache()
  47.         self.botframe = None
  48.         self.stopframe = None
  49.         self.returnframe = None
  50.         self.quitting = 0
  51.  
  52.     
  53.     def trace_dispatch(self, frame, event, arg):
  54.         if self.quitting:
  55.             return None
  56.         
  57.         if event == 'line':
  58.             return self.dispatch_line(frame)
  59.         
  60.         if event == 'call':
  61.             return self.dispatch_call(frame, arg)
  62.         
  63.         if event == 'return':
  64.             return self.dispatch_return(frame, arg)
  65.         
  66.         if event == 'exception':
  67.             return self.dispatch_exception(frame, arg)
  68.         
  69.         print 'bdb.Bdb.dispatch: unknown debugging event:', `event`
  70.         return self.trace_dispatch
  71.  
  72.     
  73.     def dispatch_line(self, frame):
  74.         if self.stop_here(frame) or self.break_here(frame):
  75.             self.user_line(frame)
  76.             if self.quitting:
  77.                 raise BdbQuit
  78.             
  79.         
  80.         return self.trace_dispatch
  81.  
  82.     
  83.     def dispatch_call(self, frame, arg):
  84.         if self.botframe is None:
  85.             self.botframe = frame.f_back
  86.             return self.trace_dispatch
  87.         
  88.         if not self.stop_here(frame):
  89.             pass
  90.         if not self.break_anywhere(frame):
  91.             return None
  92.         
  93.         self.user_call(frame, arg)
  94.         if self.quitting:
  95.             raise BdbQuit
  96.         
  97.         return self.trace_dispatch
  98.  
  99.     
  100.     def dispatch_return(self, frame, arg):
  101.         if self.stop_here(frame) or frame == self.returnframe:
  102.             self.user_return(frame, arg)
  103.             if self.quitting:
  104.                 raise BdbQuit
  105.             
  106.         
  107.         return self.trace_dispatch
  108.  
  109.     
  110.     def dispatch_exception(self, frame, arg):
  111.         if self.stop_here(frame):
  112.             self.user_exception(frame, arg)
  113.             if self.quitting:
  114.                 raise BdbQuit
  115.             
  116.         
  117.         return self.trace_dispatch
  118.  
  119.     
  120.     def stop_here(self, frame):
  121.         if frame is self.stopframe:
  122.             return True
  123.         
  124.         while frame is not None and frame is not self.stopframe:
  125.             if frame is self.botframe:
  126.                 return True
  127.             
  128.             frame = frame.f_back
  129.         return False
  130.  
  131.     
  132.     def break_here(self, frame):
  133.         filename = self.canonic(frame.f_code.co_filename)
  134.         if not (filename in self.breaks):
  135.             return False
  136.         
  137.         lineno = frame.f_lineno
  138.         if not (lineno in self.breaks[filename]):
  139.             return False
  140.         
  141.         (bp, flag) = effective(filename, lineno, frame)
  142.         if bp:
  143.             self.currentbp = bp.number
  144.             if flag and bp.temporary:
  145.                 self.do_clear(str(bp.number))
  146.             
  147.             return True
  148.         else:
  149.             return False
  150.  
  151.     
  152.     def do_clear(self, arg):
  153.         raise NotImplementedError, 'subclass of bdb must implement do_clear()'
  154.  
  155.     
  156.     def break_anywhere(self, frame):
  157.         return self.breaks.has_key(self.canonic(frame.f_code.co_filename))
  158.  
  159.     
  160.     def user_call(self, frame, argument_list):
  161.         '''This method is called when there is the remote possibility
  162.         that we ever need to stop in this function.'''
  163.         pass
  164.  
  165.     
  166.     def user_line(self, frame):
  167.         '''This method is called when we stop or break at this line.'''
  168.         pass
  169.  
  170.     
  171.     def user_return(self, frame, return_value):
  172.         '''This method is called when a return trap is set here.'''
  173.         pass
  174.  
  175.     
  176.     def user_exception(self, frame, .4):
  177.         '''This method is called if an exception occurs,
  178.         but only if we are to stop at or just below this level.'''
  179.         (exc_type, exc_value, exc_traceback) = .4
  180.  
  181.     
  182.     def set_step(self):
  183.         '''Stop after one line of code.'''
  184.         self.stopframe = None
  185.         self.returnframe = None
  186.         self.quitting = 0
  187.  
  188.     
  189.     def set_next(self, frame):
  190.         '''Stop on the next line in or below the given frame.'''
  191.         self.stopframe = frame
  192.         self.returnframe = None
  193.         self.quitting = 0
  194.  
  195.     
  196.     def set_return(self, frame):
  197.         '''Stop when returning from the given frame.'''
  198.         self.stopframe = frame.f_back
  199.         self.returnframe = frame
  200.         self.quitting = 0
  201.  
  202.     
  203.     def set_trace(self):
  204.         '''Start debugging from here.'''
  205.         frame = sys._getframe().f_back
  206.         self.reset()
  207.         while frame:
  208.             frame.f_trace = self.trace_dispatch
  209.             self.botframe = frame
  210.             frame = frame.f_back
  211.         self.set_step()
  212.         sys.settrace(self.trace_dispatch)
  213.  
  214.     
  215.     def set_continue(self):
  216.         self.stopframe = self.botframe
  217.         self.returnframe = None
  218.         self.quitting = 0
  219.         if not (self.breaks):
  220.             sys.settrace(None)
  221.             frame = sys._getframe().f_back
  222.             while frame and frame is not self.botframe:
  223.                 del frame.f_trace
  224.                 frame = frame.f_back
  225.         
  226.  
  227.     
  228.     def set_quit(self):
  229.         self.stopframe = self.botframe
  230.         self.returnframe = None
  231.         self.quitting = 1
  232.         sys.settrace(None)
  233.  
  234.     
  235.     def set_break(self, filename, lineno, temporary = 0, cond = None):
  236.         filename = self.canonic(filename)
  237.         import linecache
  238.         line = linecache.getline(filename, lineno)
  239.         if not line:
  240.             return 'Line %s:%d does not exist' % (filename, lineno)
  241.         
  242.         if not (filename in self.breaks):
  243.             self.breaks[filename] = []
  244.         
  245.         list = self.breaks[filename]
  246.         if not (lineno in list):
  247.             list.append(lineno)
  248.         
  249.         bp = Breakpoint(filename, lineno, temporary, cond)
  250.  
  251.     
  252.     def clear_break(self, filename, lineno):
  253.         filename = self.canonic(filename)
  254.         if not (filename in self.breaks):
  255.             return 'There are no breakpoints in %s' % filename
  256.         
  257.         if lineno not in self.breaks[filename]:
  258.             return 'There is no breakpoint at %s:%d' % (filename, lineno)
  259.         
  260.         for bp in Breakpoint.bplist[(filename, lineno)][:]:
  261.             bp.deleteMe()
  262.         
  263.         if not Breakpoint.bplist.has_key((filename, lineno)):
  264.             self.breaks[filename].remove(lineno)
  265.         
  266.         if not self.breaks[filename]:
  267.             del self.breaks[filename]
  268.         
  269.  
  270.     
  271.     def clear_bpbynumber(self, arg):
  272.         
  273.         try:
  274.             number = int(arg)
  275.         except:
  276.             return 'Non-numeric breakpoint number (%s)' % arg
  277.  
  278.         
  279.         try:
  280.             bp = Breakpoint.bpbynumber[number]
  281.         except IndexError:
  282.             return 'Breakpoint number (%d) out of range' % number
  283.  
  284.         if not bp:
  285.             return 'Breakpoint (%d) already deleted' % number
  286.         
  287.         self.clear_break(bp.file, bp.line)
  288.  
  289.     
  290.     def clear_all_file_breaks(self, filename):
  291.         filename = self.canonic(filename)
  292.         if not (filename in self.breaks):
  293.             return 'There are no breakpoints in %s' % filename
  294.         
  295.         for line in self.breaks[filename]:
  296.             blist = Breakpoint.bplist[(filename, line)]
  297.             for bp in blist:
  298.                 bp.deleteMe()
  299.             
  300.         
  301.         del self.breaks[filename]
  302.  
  303.     
  304.     def clear_all_breaks(self):
  305.         if not (self.breaks):
  306.             return 'There are no breakpoints'
  307.         
  308.         for bp in Breakpoint.bpbynumber:
  309.             if bp:
  310.                 bp.deleteMe()
  311.                 continue
  312.         
  313.         self.breaks = { }
  314.  
  315.     
  316.     def get_break(self, filename, lineno):
  317.         filename = self.canonic(filename)
  318.         if filename in self.breaks:
  319.             pass
  320.         return lineno in self.breaks[filename]
  321.  
  322.     
  323.     def get_breaks(self, filename, lineno):
  324.         filename = self.canonic(filename)
  325.         if not filename in self.breaks and lineno in self.breaks[filename] and Breakpoint.bplist[(filename, lineno)]:
  326.             pass
  327.         return []
  328.  
  329.     
  330.     def get_file_breaks(self, filename):
  331.         filename = self.canonic(filename)
  332.         if filename in self.breaks:
  333.             return self.breaks[filename]
  334.         else:
  335.             return []
  336.  
  337.     
  338.     def get_all_breaks(self):
  339.         return self.breaks
  340.  
  341.     
  342.     def get_stack(self, f, t):
  343.         stack = []
  344.         if t and t.tb_frame is f:
  345.             t = t.tb_next
  346.         
  347.         while f is not None:
  348.             stack.append((f, f.f_lineno))
  349.             if f is self.botframe:
  350.                 break
  351.             
  352.             f = f.f_back
  353.         stack.reverse()
  354.         i = max(0, len(stack) - 1)
  355.         while t is not None:
  356.             stack.append((t.tb_frame, t.tb_lineno))
  357.             t = t.tb_next
  358.         return (stack, i)
  359.  
  360.     
  361.     def format_stack_entry(self, frame_lineno, lprefix = ': '):
  362.         import linecache
  363.         import repr
  364.         (frame, lineno) = frame_lineno
  365.         filename = self.canonic(frame.f_code.co_filename)
  366.         s = filename + '(' + `lineno` + ')'
  367.         if frame.f_code.co_name:
  368.             s = s + frame.f_code.co_name
  369.         else:
  370.             s = s + '<lambda>'
  371.         if '__args__' in frame.f_locals:
  372.             args = frame.f_locals['__args__']
  373.         else:
  374.             args = None
  375.         if args:
  376.             s = s + repr.repr(args)
  377.         else:
  378.             s = s + '()'
  379.         if '__return__' in frame.f_locals:
  380.             rv = frame.f_locals['__return__']
  381.             s = s + '->'
  382.             s = s + repr.repr(rv)
  383.         
  384.         line = linecache.getline(filename, lineno)
  385.         if line:
  386.             s = s + lprefix + line.strip()
  387.         
  388.         return s
  389.  
  390.     
  391.     def run(self, cmd, globals = None, locals = None):
  392.         if globals is None:
  393.             import __main__
  394.             globals = __main__.__dict__
  395.         
  396.         if locals is None:
  397.             locals = globals
  398.         
  399.         self.reset()
  400.         sys.settrace(self.trace_dispatch)
  401.         if not isinstance(cmd, types.CodeType):
  402.             cmd = cmd + '\n'
  403.         
  404.         
  405.         try:
  406.             exec cmd in globals, locals
  407.         except BdbQuit:
  408.             pass
  409.         finally:
  410.             self.quitting = 1
  411.             sys.settrace(None)
  412.  
  413.  
  414.     
  415.     def runeval(self, expr, globals = None, locals = None):
  416.         if globals is None:
  417.             import __main__
  418.             globals = __main__.__dict__
  419.         
  420.         if locals is None:
  421.             locals = globals
  422.         
  423.         self.reset()
  424.         sys.settrace(self.trace_dispatch)
  425.         if not isinstance(expr, types.CodeType):
  426.             expr = expr + '\n'
  427.         
  428.         
  429.         try:
  430.             return eval(expr, globals, locals)
  431.         except BdbQuit:
  432.             pass
  433.         finally:
  434.             self.quitting = 1
  435.             sys.settrace(None)
  436.  
  437.  
  438.     
  439.     def runctx(self, cmd, globals, locals):
  440.         self.run(cmd, globals, locals)
  441.  
  442.     
  443.     def runcall(self, func, *args):
  444.         self.reset()
  445.         sys.settrace(self.trace_dispatch)
  446.         res = None
  447.         
  448.         try:
  449.             res = func(*args)
  450.         except BdbQuit:
  451.             pass
  452.         finally:
  453.             self.quitting = 1
  454.             sys.settrace(None)
  455.  
  456.         return res
  457.  
  458.  
  459.  
  460. def set_trace():
  461.     Bdb().set_trace()
  462.  
  463.  
  464. class Breakpoint:
  465.     '''Breakpoint class
  466.  
  467.     Implements temporary breakpoints, ignore counts, disabling and
  468.     (re)-enabling, and conditionals.
  469.  
  470.     Breakpoints are indexed by number through bpbynumber and by
  471.     the file,line tuple using bplist.  The former points to a
  472.     single instance of class Breakpoint.  The latter points to a
  473.     list of such instances since there may be more than one
  474.     breakpoint per line.
  475.  
  476.     '''
  477.     next = 1
  478.     bplist = { }
  479.     bpbynumber = [
  480.         None]
  481.     
  482.     def __init__(self, file, line, temporary = 0, cond = None):
  483.         self.file = file
  484.         self.line = line
  485.         self.temporary = temporary
  486.         self.cond = cond
  487.         self.enabled = 1
  488.         self.ignore = 0
  489.         self.hits = 0
  490.         self.number = Breakpoint.next
  491.         Breakpoint.next = Breakpoint.next + 1
  492.         self.bpbynumber.append(self)
  493.         if self.bplist.has_key((file, line)):
  494.             self.bplist[(file, line)].append(self)
  495.         else:
  496.             self.bplist[(file, line)] = [
  497.                 self]
  498.  
  499.     
  500.     def deleteMe(self):
  501.         index = (self.file, self.line)
  502.         self.bpbynumber[self.number] = None
  503.         self.bplist[index].remove(self)
  504.         if not self.bplist[index]:
  505.             del self.bplist[index]
  506.         
  507.  
  508.     
  509.     def enable(self):
  510.         self.enabled = 1
  511.  
  512.     
  513.     def disable(self):
  514.         self.enabled = 0
  515.  
  516.     
  517.     def bpprint(self):
  518.         if self.temporary:
  519.             disp = 'del  '
  520.         else:
  521.             disp = 'keep '
  522.         if self.enabled:
  523.             disp = disp + 'yes'
  524.         else:
  525.             disp = disp + 'no '
  526.         print '%-4dbreakpoint    %s at %s:%d' % (self.number, disp, self.file, self.line)
  527.         if self.cond:
  528.             print '\tstop only if %s' % (self.cond,)
  529.         
  530.         if self.ignore:
  531.             print '\tignore next %d hits' % self.ignore
  532.         
  533.         if self.hits:
  534.             if self.hits > 1:
  535.                 ss = 's'
  536.             else:
  537.                 ss = ''
  538.             print '\tbreakpoint already hit %d time%s' % (self.hits, ss)
  539.         
  540.  
  541.  
  542.  
  543. def effective(file, line, frame):
  544.     '''Determine which breakpoint for this file:line is to be acted upon.
  545.  
  546.     Called only if we know there is a bpt at this
  547.     location.  Returns breakpoint that was triggered and a flag
  548.     that indicates if it is ok to delete a temporary bp.
  549.  
  550.     '''
  551.     possibles = Breakpoint.bplist[(file, line)]
  552.     for i in range(0, len(possibles)):
  553.         b = possibles[i]
  554.         if b.enabled == 0:
  555.             continue
  556.         
  557.         b.hits = b.hits + 1
  558.         if not (b.cond):
  559.             if b.ignore > 0:
  560.                 b.ignore = b.ignore - 1
  561.                 continue
  562.             else:
  563.                 return (b, 1)
  564.         b.ignore > 0
  565.         
  566.         try:
  567.             val = eval(b.cond, frame.f_globals, frame.f_locals)
  568.             if val:
  569.                 if b.ignore > 0:
  570.                     b.ignore = b.ignore - 1
  571.                 else:
  572.                     return (b, 1)
  573.         continue
  574.         return (b, 0)
  575.         continue
  576.  
  577.     
  578.     return (None, None)
  579.  
  580.  
  581. class Tdb(Bdb):
  582.     
  583.     def user_call(self, frame, args):
  584.         name = frame.f_code.co_name
  585.         if not name:
  586.             name = '???'
  587.         
  588.         print '+++ call', name, args
  589.  
  590.     
  591.     def user_line(self, frame):
  592.         import linecache
  593.         name = frame.f_code.co_name
  594.         if not name:
  595.             name = '???'
  596.         
  597.         fn = self.canonic(frame.f_code.co_filename)
  598.         line = linecache.getline(fn, frame.f_lineno)
  599.         print '+++', fn, frame.f_lineno, name, ':', line.strip()
  600.  
  601.     
  602.     def user_return(self, frame, retval):
  603.         print '+++ return', retval
  604.  
  605.     
  606.     def user_exception(self, frame, exc_stuff):
  607.         print '+++ exception', exc_stuff
  608.         self.set_continue()
  609.  
  610.  
  611.  
  612. def foo(n):
  613.     print 'foo(', n, ')'
  614.     x = bar(n * 10)
  615.     print 'bar returned', x
  616.  
  617.  
  618. def bar(a):
  619.     print 'bar(', a, ')'
  620.     return a / 2
  621.  
  622.  
  623. def test():
  624.     t = Tdb()
  625.     t.run('import bdb; bdb.foo(10)')
  626.  
  627.